<?php

namespace App\Controller\Admin;

use App\Constants\ErrorCode;
use App\Constants\ServerList;
use App\Middleware\AdminMiddleware;
use App\Model\QmGameVersion;
use GuzzleHttp\Exception\GuzzleException;
use Hyperf\Guzzle\ClientFactory;
use Hyperf\Di\Annotation\Inject;
use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\GetMapping;
use Hyperf\HttpServer\Annotation\Middleware;
use Hyperf\HttpServer\Annotation\PostMapping;

#[Controller(prefix: '/admin/GameVersion'), Middleware(AdminMiddleware::class)]
class GameVersionController extends BaseController {

    /**
     * @Inject
     * @var ClientFactory
     */
    protected ClientFactory $clientFactory;

    /**
     * 获取列表
     * @return array
     */
    #[GetMapping(path: 'index')]
    public function index(): array {
        $limit = $this->request->query('size', config('apiadmin.admin_list_default'));
        $keywords = $this->request->query('game_hash', '');

        $listObj = QmGameVersion::query();
        if ($keywords) {
            $listObj = $listObj->where('game_hash', $keywords);
        }
        $listObj = $listObj->orderByDesc('id')->paginate((int)$limit);

        return $this->buildSuccess([
            'list'       => $listObj->items(),
            'count'      => $listObj->total(),
            'serverList' => ServerList::YZTT_LIST
        ]);
    }

    /**
     * 添加
     * @return array
     */
    #[PostMapping(path: 'add')]
    public function add(): array {
        $version = $this->request->post('version', '');
        $game_hash = $this->request->post('game_hash', '');

        $has = QmGameVersion::query()->where('game_hash', $game_hash)->where('version', $version)->count();
        if ($has) {
            return $this->buildFailed(ErrorCode::DATA_EXISTS, '版本号不能重复');
        }

        $confObj = new QmGameVersion();
        $confObj->game_hash = $game_hash;
        $confObj->version = $version;
        $confObj->status = 2;
        $confObj->kong_code = ServerList::YZTT_LIST[1]['code'];
        $confObj->connection_code = md5($game_hash . $version);
        $confObj->save();

        return $this->buildSuccess();
    }

    /**
     * 修改状态
     * @return array
     */
    #[GetMapping(path: 'changeStatus')]
    public function changeStatus(): array {
        $id = $this->request->query('id');
        $status = $this->request->query('status');
        QmGameVersion::query()->where('id', $id)->update([
            'status'    => $status,
            'kong_code' => ServerList::YZTT_LIST[$status]['code']
        ]);

        return $this->buildSuccess();
    }

    /**
     * 发布服务
     * @return array
     * @throws GuzzleException
     */
    #[GetMapping(path: 'publishServer')]
    public function publishServer(): array {
        $gateway = config('apiadmin.gateway_ip');
        $kongUrl = "http://{$gateway}/8001/";
        $allVersion = QmGameVersion::query()->get();
        $confArr = [];
        foreach ($allVersion as $item) {
            $confArr[$item['kong_code']][] = $item['connection_code'];
        }

        $needAdd = [];
        $needDel = [];
        $client = $this->clientFactory->create(['verify' => false]);
        $allService = $client->get($kongUrl . "services/");
        $allService = json_decode($allService->getBody()->getContents(), true);
        if ($allService['data']) {
            $serviceMap = array_column($allService['data'], 'id', 'name');
        } else {
            return $this->buildFailed(ErrorCode::NOT_EXISTS, 'Service 不存在');
        }

        foreach (ServerList::YZTT_LIST as $server) {
            $response = $client->get($kongUrl . "services/{$server['code']}/routes");
            $content = json_decode($response->getBody()->getContents(), true);
            if ($content['data']) {
                $newConfArr = [];
                if (isset($confArr[$server['code']])) {
                    $newConfArr = $confArr[$server['code']]; // 全部新的配置
                }

                foreach ($content['data'] as $datum) { // 遍历全部老的
                    $index = array_search($datum['headers']['Connection-Code'], $newConfArr);
                    if ($index === false) {
                        $needDel[] = $datum['id'];
                    } else {
                        unset($newConfArr[$index]);
                    }
                }

                $needAdd[$server['code']] = array_values($newConfArr);
            } else {
                if (isset($confArr[$server['code']])) {
                    $needAdd[$server['code']] = $confArr[$server['code']];
                }
            }
        }

        if ($needDel) {
            foreach ($needDel as $ndc) {
                $client->delete($kongUrl . "routes/{$ndc}");
            }
        }

        if ($needAdd) {
            foreach ($needAdd as $serviceName => $connectionCodeArr) {
                if (isset($serviceMap[$serviceName])) {
                    $serviceId = $serviceMap[$serviceName];

                    if (count($connectionCodeArr)) {
                        foreach ($connectionCodeArr as $connectionCode) {
                            $client->post($kongUrl . "routes", [
                                'json' => [
                                    'name'          => md5(uniqid()),
                                    'hosts'         => ["sldnf.qingmanet.com", $gateway],
                                    'paths'         => ['/api/', '/sldnfInsideService/'],
                                    'strip_path'    => false,
                                    'preserve_host' => true,
                                    'service'       => ['id' => $serviceId],
                                    'headers'       => ["Connection-Code" => [$connectionCode]]
                                ]
                            ]);
                        }
                    }
                }
            }
        }

        return $this->buildSuccess([
            $needAdd,
            $needDel
        ]);
    }

}